#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
音频格式转换器
将AAC、M4A格式的音频文件转换为MP3格式
"""

import os
import sys
import subprocess
import re
import logging
from concurrent.futures import ThreadPoolExecutor, as_completed
import argparse
import time

# 将项目根目录添加到Python搜索路径
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from src.utils import setup_logger, create_dir_if_not_exists, write_log_to_file
from config import settings

# 设置日志记录器
logger = setup_logger('audio_converter')

class AudioConverter:
    """音频格式转换类"""
    def __init__(self):
        # 检查FFmpeg是否已安装
        self.ffmpeg_available = self._check_ffmpeg()
        
    def _check_ffmpeg(self):
        """检查系统是否安装了FFmpeg"""
        try:
            # 尝试运行ffmpeg命令获取版本信息
            result = subprocess.run(['ffmpeg', '-version'], 
                                   stdout=subprocess.PIPE, 
                                   stderr=subprocess.PIPE, 
                                   check=True)
            logger.info(f"FFmpeg已安装: {result.stdout.decode('utf-8').split('\n')[0]}")
            return True
        except (subprocess.SubprocessError, FileNotFoundError):
            logger.error("未找到FFmpeg。请先安装FFmpeg工具，然后再运行此脚本。")
            logger.error("安装指南: https://ffmpeg.org/download.html")
            write_log_to_file("未找到FFmpeg，转换任务无法执行", "ERROR")
            return False
    
    def convert_file(self, input_path, output_path, bitrate='320k'):
        """将单个音频文件转换为MP3格式
        
        Args:
            input_path: 输入文件路径
            output_path: 输出文件路径
            bitrate: MP3比特率，默认为320k
        
        Returns:
            bool: 转换是否成功
        """
        if not self.ffmpeg_available:
            return False
            
        try:
            # 使用FFmpeg转换音频格式
            # -i: 输入文件
            # -vn: 忽略视频流
            # -acodec libmp3lame: 使用MP3编码器
            # -ab: 设置音频比特率
            # -y: 覆盖已存在的文件
            command = [
                'ffmpeg',
                '-i', input_path,
                '-vn',  # 忽略视频流
                '-acodec', 'libmp3lame',  # 使用MP3编码器
                '-ab', bitrate,  # 设置音频比特率
                '-y',  # 覆盖已存在的文件
                output_path
            ]
            
            logger.info(f"开始转换: {input_path} -> {output_path}")
            
            # 执行FFmpeg命令
            result = subprocess.run(
                command,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE
            )
            
            if result.returncode == 0:
                logger.info(f"转换成功: {input_path} -> {output_path}")
                write_log_to_file(f"音频转换成功: {input_path} -> {output_path}", "INFO")
                return True
            else:
                error_msg = result.stderr.decode('utf-8', errors='ignore')
                logger.error(f"转换失败: {input_path}, 错误: {error_msg}")
                write_log_to_file(f"音频转换失败: {input_path}, 错误: {error_msg}", "ERROR")
                return False
        except Exception as e:
            logger.error(f"转换异常: {input_path}, 错误: {str(e)}")
            write_log_to_file(f"音频转换异常: {input_path}, 错误: {str(e)}", "ERROR")
            return False
    
    def scan_and_convert(self, directory, output_dir=None, recursive=True, bitrate='320k', max_workers=4):
        """扫描目录并转换所有AAC和M4A文件
        
        Args:
            directory: 要扫描的目录
            output_dir: 输出目录，如果为None则在原目录创建MP3文件
            recursive: 是否递归扫描子目录
            bitrate: MP3比特率
            max_workers: 最大并发数
        
        Returns:
            tuple: (成功数量, 失败数量)
        """
        if not self.ffmpeg_available:
            return 0, 0
            
        if not os.path.exists(directory):
            logger.error(f"目录不存在: {directory}")
            return 0, 0
            
        # 创建输出目录（如果指定）
        if output_dir and not os.path.exists(output_dir):
            create_dir_if_not_exists(output_dir)
            
        # 要转换的文件列表
        files_to_convert = []
        
        # 定义要匹配的音频格式正则表达式
        audio_pattern = re.compile(r'\.(aac|m4a)$', re.IGNORECASE)
        
        # 扫描目录
        scan_mode = "递归" if recursive else "非递归"
        logger.info(f"开始扫描{scan_mode}目录: {directory}, 寻找AAC和M4A文件...")
        
        if recursive:
            for root, _, files in os.walk(directory):
                for file in files:
                    if audio_pattern.search(file):
                        input_path = os.path.join(root, file)
                        files_to_convert.append(input_path)
        else:
            for file in os.listdir(directory):
                file_path = os.path.join(directory, file)
                if os.path.isfile(file_path) and audio_pattern.search(file):
                    files_to_convert.append(file_path)
        
        total_files = len(files_to_convert)
        logger.info(f"找到{total_files}个需要转换的音频文件")
        write_log_to_file(f"找到{total_files}个需要转换的音频文件", "INFO")
        
        if total_files == 0:
            return 0, 0
            
        # 使用线程池进行并发转换
        success_count = 0
        failed_count = 0
        
        start_time = time.time()
        
        with ThreadPoolExecutor(max_workers=min(max_workers, total_files)) as executor:
            # 提交所有转换任务
            future_to_file = {}
            
            for input_path in files_to_convert:
                # 确定输出路径
                if output_dir:
                    # 保持目录结构
                    rel_path = os.path.relpath(os.path.dirname(input_path), directory)
                    output_subdir = os.path.join(output_dir, rel_path)
                    create_dir_if_not_exists(output_subdir)
                    
                    # 创建输出文件名
                    base_name = os.path.basename(input_path)
                    output_name = os.path.splitext(base_name)[0] + '.mp3'
                    output_path = os.path.join(output_subdir, output_name)
                else:
                    # 在原目录创建MP3文件
                    output_path = os.path.splitext(input_path)[0] + '.mp3'
                
                # 提交任务
                future_to_file[executor.submit(self.convert_file, input_path, output_path, bitrate)] = input_path
            
            # 处理完成的任务
            for future in as_completed(future_to_file):
                input_path = future_to_file[future]
                try:
                    success = future.result()
                    if success:
                        success_count += 1
                    else:
                        failed_count += 1
                except Exception as e:
                    logger.error(f"任务异常: {input_path}, 错误: {str(e)}")
                    failed_count += 1
        
        end_time = time.time()
        elapsed_time = end_time - start_time
        
        logger.info(f"音频转换完成: 成功{success_count}个, 失败{failed_count}个, 总耗时: {elapsed_time:.2f}秒")
        write_log_to_file(f"音频转换完成: 成功{success_count}个, 失败{failed_count}个, 总耗时: {elapsed_time:.2f}秒", "INFO")
        
        return success_count, failed_count

def main():
    """主函数"""
    # 解析命令行参数
    parser = argparse.ArgumentParser(description='音频格式转换器 - 将AAC、M4A格式转换为MP3')
    parser.add_argument('-d', '--directory', type=str, 
                        default=settings.MUSIC_SAVE_PATH, 
                        help=f'要扫描的目录 (默认: {settings.MUSIC_SAVE_PATH})')
    parser.add_argument('-o', '--output-dir', type=str, 
                        default=None, 
                        help='输出目录 (默认: 在原目录创建MP3文件)')
    parser.add_argument('-r', '--recursive', action='store_true', 
                        help='是否递归扫描子目录 (默认: 是)')
    parser.add_argument('-n', '--non-recursive', action='store_true', 
                        help='不递归扫描子目录')
    parser.add_argument('-b', '--bitrate', type=str, 
                        default='320k', 
                        help='MP3比特率 (默认: 320k)')
    parser.add_argument('-w', '--workers', type=int, 
                        default=4, 
                        help='最大并发数 (默认: 4)')
    
    args = parser.parse_args()
    
    # 确定是否递归
    recursive = not args.non_recursive
    
    # 创建转换器实例
    converter = AudioConverter()
    
    # 开始扫描和转换
    success, failed = converter.scan_and_convert(
        directory=args.directory,
        output_dir=args.output_dir,
        recursive=recursive,
        bitrate=args.bitrate,
        max_workers=args.workers
    )
    
    # 输出结果摘要
    print(f"\n转换结果摘要:")
    print(f"成功转换: {success} 个文件")
    print(f"转换失败: {failed} 个文件")
    print(f"总文件数: {success + failed} 个文件")
    
    if not converter.ffmpeg_available:
        print("\n错误: 未找到FFmpeg。请先安装FFmpeg工具，然后再运行此脚本。")
        print("安装指南: https://ffmpeg.org/download.html")
        sys.exit(1)
    
    sys.exit(0)

if __name__ == '__main__':
    main()